from sys import argv
from PIL import Image
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from random import choices

class MyPyOpenGLTest:
    def __init__(self, width=640, height=480, title='太阳地球月亮'):
        glutInit(len(argv), argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(width, height)
        glutInitWindowPosition(350, 200)
        self.window = glutCreateWindow(title.encode('gbk'))
        glutDisplayFunc(self.draw)
        glutIdleFunc(self.draw)
        glutReshapeFunc(self.reshape)
        glClearColor(1, 1, 1, 1)
        # 启用深度测试
        glEnable(GL_DEPTH_TEST)
        # 自动生成适合球面映射的纹理坐标
        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
        # glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_OBJECT_LINEAR)
        # glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_OBJECT_LINEAR)
        glEnable(GL_TEXTURE_GEN_S)
        glEnable(GL_TEXTURE_GEN_T)

        # 设置光滑渲染模式
        glShadeModel(GL_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POLYGON_SMOOTH)
        glHint(GL_POINT_SMOOTH_HINT, GL_NICEST)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST)
        # 加载纹理
        self.load_texture()

        # 加载图片，如果不加最后的参数-1，图片是上下颠倒的
        self.image = (Image.open('author.png')
                      .resize((128, 128)).tobytes('raw', 'RGB', 0, -1))
        self.angle_earth_sun = 2
        self.angle_moon_earth = 24

    def load_texture(self):
        images = ('sun.bmp', 'earth.bmp', 'moon.bmp');

        for index, image in enumerate(images, start=1):
            im = Image.open(image)
            width, height = im.size
            im = im.tobytes('raw', 'RGB', 0, -1)

            glBindTexture(GL_TEXTURE_2D, index)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
                         0, GL_RGB, GL_UNSIGNED_BYTE, im)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)


    def reshape(self, w, h):
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            glViewport(0, 0, w, h)
            aspect = w / h
            gluPerspective(45, aspect, 1, 1000)
            glMatrixMode(GL_MODELVIEW)
    def draw(self):
        # 每次绘制图形之前清除颜色缓冲区和深度缓冲区中的信息
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        # 切换到模型观察矩阵，才能正确绘制图形
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        # 定位三维光栅位置
        glRasterPos3f(160, -200, -500)

        # 绘制位图图像，前面两个参数分别表示高度和宽度
        glDrawPixels(128, 128, GL_RGB, GL_UNSIGNED_BYTE, self.image)
        glLoadIdentity()
        glEnable(GL_TEXTURE_2D)

        # 绘制太阳
        glTranslatef(0, 0, -450)
        glColor3f(1, 0, 0)
        glBindTexture(GL_TEXTURE_2D, 1)
        glutSolidSphere(50, 30, 30)

        # 绘制地球
        glColor3f(0, 0, 1)
        # 黄赤交角, 地球公转轨道面（黄道面）与赤道面（天赤道面）的交点
        # 也称为太阳赤纬角或黄赤大距
        glRotate(23.26, 0, 0, 1)
        glRotate(6, 1, 1, 1)

        # 绕太阳旋转
        glRotate(self.angle_earth_sun, 0, 1, 0)
        # 地球与太阳的距离
        glTranslatef(200, 0, 0)
        glBindTexture(GL_TEXTURE_2D, 2)
        glutSolidSphere(20, 30, 30)

        # 绘制月亮
        glRotate(6, 1, 1, 1)
        # 绕地球旋转
        glRotate(self.angle_moon_earth, 0, 1, 0)
        glColor3f(1, 1, 0)
        # 月亮与地球的距离
        glTranslatef(30, 0, 0)
        glBindTexture(GL_TEXTURE_2D, 3)
        glutSolidSphere(5, 15, 15)
        glDisable(GL_TEXTURE_2D)

        # 修改旋转角度
        self.angle_earth_sun = self.angle_earth_sun + 0.03
        if self.angle_earth_sun > 360:
            self.angle_earth_sun = 2
        self.angle_moon_earth = self.angle_moon_earth + 0.024
        if self.angle_moon_earth > 360:
            self.angle_moon_earth = 24
        glMatrixMode(GL_MODELVIEW)

        # 交换缓冲区，更新图形
        glutSwapBuffers()

    def mainloop(self):
        # 显示窗口，启动消息主循环
        glutMainLoop()

if __name__ == '__main__':
    MyPyOpenGLTest().mainloop()
